home *** CD-ROM | disk | FTP | other *** search
- /*
- (C) Copyright Taiichi Yuasa and Masami Hagiya, 1984. All rights reserved.
- */
-
- #include "include.h"
-
- struct nsection {
- unsigned int logical_start;
- unsigned int logical_length;
- unsigned int file_start;
- unsigned int file_length;
- unsigned int file_reloc;
- unsigned int file_reloc_length;
- unsigned int attributes;
- };
-
- struct prformat {
- unsigned short magic_number; /* magic */
- unsigned short format_rev_number; /* format rev. number */
- unsigned short num_non_exec_sect; /* # of non-exec. sects */
- unsigned short num_exec_sect; /* # of executable sects */
- struct nsection syshead; /* system header */
- struct nsection symbolt; /* symbol table */
- struct nsection ds; /* */
- struct nsection dl; /* */
- struct nsection lt; /* */
- struct nsection exec[2]; /* two executable sections */
- };
-
- struct system_header {
- unsigned int start_pc;
- unsigned int stacks;
- unsigned int unlabeled;
- unsigned int time_stamp;
- unsigned int user_rev_number;
- unsigned short flags;
- unsigned short ntasks;
- unsigned short nchannels;
- };
-
- struct stack_register {
- unsigned int fp;
- unsigned int sp;
- unsigned int sl;
- unsigned int sb;
- };
-
- #define NUM_ENVIRON 6
-
- /*
- saved_init copies arg and environment variables from top of data
- segment to stack area and shrink the memory.
-
- When execed by system, arg and environment variables are as follows;
-
- break value --> | |
- +--------------------+
- | environ array ptr |--------+
- +--------------------+ |
- | argument array ptr |----+ |
- +--------------------+ | |
- AC2 ----------> | argument count | | |
- +--------------------+ | |
- | | | |
- +============> | environment | | |
- ! | | | |
- ! +--------------------+ | |
- ! | | | |
- ! +====> | arguments | | |
- ! ! | | | |
- ! ! +--------------------+ | |
- +====== ! ===== | environment array |<-- | --+
- ! +--------------------+ |
- +====== | argument array |<---+
- +--------------------+
- | |
-
- */
-
-
- void
- saved_init()
- {
- char *break_value;
- char *new_break_value;
- char *sbrk();
- char *old_start; /* old data area start byte address */
- char *new_start; /* new data area start byte address */
- int size; /* data size */
- int *sp; /* wide stack pointer */
- int i;
-
- int argc;
- char **argv;
- char **envp;
-
- break_value = sbrk(0);
-
- argc = *((unsigned int *)break_value - 3); /* arg count */
- argv =
- (char **)(*((unsigned int *)break_value - 2)); /* arg array ptr */
- envp =
- (char **)(*((unsigned int *)break_value - 1)); /* env array ptr */
-
- /*
- old_start will be new break value after initialization.
- */
- new_break_value = old_start = (char *)&argv[0];
-
- /*
- calc total space required. size is byte size and is multiple of 4
- becase both break_value and argv[0] are double word boundary.
- */
- size = break_value - old_start;
-
- /* allocate space from stack. */
- sp = getsp(); /* current stack pointer */
- setsp(sp + size / 4); /* extent stack */
-
- new_start = (char *)(sp + 1);
-
- blockmove(new_start, old_start, size);
-
- /*
- set up new argv and new envp
- */
- argv = ((unsigned int)argv - (old_start - new_start) / 2);
- envp = ((unsigned int)envp - (old_start - new_start) / 2);
-
- for (i = 0; i < argc; i++)
- argv[i] -= (old_start - new_start);
-
- for (i = 0; i < NUM_ENVIRON; i++)
- envp[i] -= (old_start - new_start);
-
- new_break_value =
- (((unsigned int)new_break_value + PAGESIZE -1 ) / PAGESIZE) * PAGESIZE;
-
- brk(new_break_value); /* shrink memory */
-
- main(argc, argv, envp); /* call main routine */
-
- exit(0);
- }
-
- filecpy(to, from, n)
- FILE *to, *from;
- int n;
- {
- char buffer[BUFSIZ];
-
- for (;;)
- if (n > BUFSIZ) {
- fread(buffer, BUFSIZ, 1, from);
- fwrite(buffer, BUFSIZ, 1, to);
- n -= BUFSIZ;
- } else if (n > 0) {
- fread(buffer, n, 1, from);
- fwrite(buffer, n, 1, to);
- break;
- } else
- break;
- }
-
- memory_save(original_file, save_file)
- char *original_file, *save_file;
- {
- int s, n;
- char *data_start;
- int data_size;
- int orig_e0_start, orig_e0_len, orig_e1_start, orig_e1_len;
- char *p, *sbrk();
- void SVINIT(); /* special initializer */
- FILE *in, *out;
- struct prformat head;
- struct system_header system;
- struct stack_register sregs;
- char buffer0[BUFSIZ], buffer1[BUFSIZ];
- char buffer[BUFSIZ];
-
- out = fopen(save_file, "w+");
- if (out == NULL) FEerror("Can't open output file.", 0);
- setbuf(out, buffer0);
-
- in = fopen(original_file, "r");
- if (in == NULL) FEerror("Can't open original KCl.", 0);
- setbuf(in, buffer1);
-
- /*
- First, we must build file header. File header is built
- by modifying the origial program's file header.
- */
- fread((char *)&head, sizeof(struct prformat), 1, in);
-
- orig_e0_start = head.exec[0].file_start;
- orig_e0_len = head.exec[0].file_length;
- orig_e1_start = head.exec[1].file_start;
- orig_e1_len = head.exec[1].file_length;
-
- data_size = sbrk(0) - (char *)034000000000;
- head.exec[1].file_start = (orig_e0_start + data_size + 02000) & ~01777;
- s = head.exec[1].file_start - orig_e1_start;
- head.symbolt.file_start += s;
- head.ds.file_start += s;
- head.dl.file_start += s;
- head.lt.file_start += s;
- head.exec[0].logical_length += (s / 2);
- head.exec[0].file_length = data_size;
-
- fwrite((char *)&head, sizeof(struct prformat), 1, out); /* header */
-
- /*
- Start_pc should be changed to special initializer for
- a saved program.
- */
- fread((char *)&system, sizeof(system), 1, in);
- system.start_pc = &SVINIT;
- system.stacks = *(unsigned int *)016000000024 -
- *(unsigned int *)016000000026;
- fwrite((char *)&system, sizeof(system), 1, out);
-
- /*
- gap
- */
- filecpy(out, in, orig_e0_start - sizeof(struct prformat)
- - sizeof(struct system_header));
-
- /*
- data segment
- */
- for (p = (char *)034000000000, n = data_size;
- ;p += BUFSIZ, n -= BUFSIZ)
- if (n > BUFSIZ)
- fwrite(p, BUFSIZ, 1, out);
- else if (n > 0) {
- fwrite(p, n, 1, out);
- break;
- } else
- break;
-
- /*
- gap
- */
- zero(buffer, BUFSIZ);
- fwrite(buffer,
- head.exec[1].file_start - (head.exec[0].file_start + data_size),
- 1,
- out);
-
- /*
- text segment
- */
- fseek(in, orig_e1_start, 0);
- filecpy(out, in, head.exec[1].file_length);
-
- /*
- others
- */
- filecpy(out, in, head.symbolt.file_length);
- filecpy(out, in, head.ds.file_length);
- filecpy(out, in, head.dl.file_length);
- filecpy(out, in, head.lt.file_length);
-
- fclose(out);
- fclose(in);
-
- chmod(save_file, 0777); /* change file mode */
- }
-
- Lsave()
- {
- char filename[256];
-
- check_arg(1);
- check_type_or_pathname_string_symbol_stream(&vs_base[0]);
- coerce_to_filename(vs_base[0], filename);
- memory_save(kcl_self, filename);
- exit(0);
- }
-
- init_dguxsave()
- {
- make_function("SAVE", Lsave);
- }
-